package my.utils.markdown.markdownformat;

import lombok.extern.slf4j.Slf4j;
import my.utils.markdown.markdownformat.domain.ImageFile;
import my.utils.markdown.markdownformat.domain.MarkdownFile;
import my.utils.markdown.markdownformat.filter.MarkdownFilter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.FileSet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class FormatMarkdown {
    //需要格式化的根文件夹地址 例："F:\\Java就业班资料\\笔记资料\\框架阶段\\21-Zookeeper（双元）"
    private static final String sourceDirectory = "F:\\Java就业班资料\\笔记资料\\黑马头条2.0-备课版-资料和讲义\\黑马头条讲义md文件\\黑马头条讲义md文件";
    //将格式化的文件存放到此根目录 例："D:\\新建文件夹\\讲义"
    private static final String targetDirectory = "C:\\Users\\Administrator\\Desktop\\test\\新建文件夹";
    //临时文件存放目录 例："D:\\新建文件夹\\Temp\\Zookeeper"
    private static final String temp = "C:\\Users\\Administrator\\Desktop\\test\\新建文件夹\\Temp";
    //打包文件编码 例："UTF-8"、"GBK"
    public final static String encoding = "GBK";
    //开启zip重复导出检查
    public static boolean checkZip = false;
    //是否要格式化markdown
    public static boolean formatMarkdown = true;

    public static void main(String[] args) {
        //是否要格式化markdown
        if (formatMarkdown) {

            Collection<File> listFiles = getListFiles(sourceDirectory);
            for (File markdown : listFiles) {
                formatMarkdown(markdown);
            }
        }
        //将临时文件中的内容每个md文档打成zip包到目标目录
        Collection<File> listFilesFormatted = getListFiles(temp);
        for (File file : listFilesFormatted) {
            if (checkZip) {
                if (checkIsExistZip(file)) {
                    //文件夹中已经存在相应的PDF
                    continue;
                }
            }
            //找到未生成Zip文件的MD文档，开始导出
            toZip(file);
        }
    }


    /*public void testAll() {
        //是否要格式化markdown
        if (formatMarkdown) {

            Collection<File> listFiles = getListFiles(sourceDirectory);
            for (File markdown : listFiles) {
                formatMarkdown(markdown);
            }
        }
        //将临时文件中的内容每个md文档打成zip包到目标目录
        Collection<File> listFilesFormatted = getListFiles(temp);
        for (File file : listFilesFormatted) {
            if (checkZip) {
                if (checkIsExistZip(file)) {
                    //文件夹中已经存在相应的PDF
                    continue;
                }
            }
            //找到未生成Zip文件的MD文档，开始导出
            toZip(file);
        }
    }*/

    private static Collection<File> getListFiles(String sourceDirectory) {
        Collection<File> listFiles = FileUtils.listFiles(
                new File(sourceDirectory),
                new MarkdownFilter(),
                FileFilterUtils.trueFileFilter()
        );
        return listFiles;
    }

    private static void formatMarkdown(File file) {
        //File file = new File("F:\\Java就业班资料\\笔记资料\\JavaSE进阶资料\\day10_集合03\\笔记\\day10集合03.md");
        MarkdownFile markdownFile = getMarkdownFile(file);
        int count = 1;
        try {
            List<String> oldStringList = FileUtils.readLines(file, "UTF-8");
            ArrayList<String> newStringList = new ArrayList<>();
            for (String line : oldStringList) {
                String replaceChars = line;
                if (StringUtils.startsWith(StringUtils.trimToNull(replaceChars), "!")) {
                    //去除链接两端空格
                    replaceChars = StringUtils.trimToNull(replaceChars);
                    if (StringUtils.contains(replaceChars, '\\')) {
                        //去除‘\’符号产生的影响，因为语雀不支持路径中含有‘\’, 例如： ![13_红黑树添加节点颜色](.\img\13_红黑树添加节点颜色.png)
                        replaceChars = StringUtils.replaceChars(replaceChars, '\\', '/');
                    }
                    //判断替换后 '/' 出现的次数，如果次数大于1则将'$'实例中的部分截取 ![13_红黑树添加节点颜色]($这里面的内容将被截取，包括最后面的斜杠/$img/13_红黑树添加节点颜色.png)
                    int countMatches = StringUtils.countMatches(replaceChars, "/");
                    if (countMatches > 1) {
                        //得到'/'倒数第二次出现的索引
                        int ordinalIndexOf = StringUtils.ordinalIndexOf(replaceChars, "/", countMatches - 1);
                        int index = StringUtils.indexOf(replaceChars, '(');
                        String left = StringUtils.substring(replaceChars, 0, index + 1);
                        String right = StringUtils.substring(replaceChars, ordinalIndexOf + 1, replaceChars.length());
                        replaceChars = StringUtils.join(left, right);
                    }
                    ImageFile imageFile = getImageFile(replaceChars, markdownFile);
                    //得到图片名称(无后缀)，准备判断是否包含中文
                    String oldImageName = StringUtils.remove(imageFile.getOldImageName(), imageFile.getFileSuffix());
                    if (!isAlphanumeric(oldImageName)) {
                        //图片名包含中文随机生成新的图片名
                        String newImageName = RandomStringUtils.randomAlphanumeric(10);
                        //将旧的文件名替换为新的文件名
                        imageFile.updateImageName(newImageName);
                    }
                    //![1591322466820](assets\1591322466820.png)
                    String newImageName = imageFile.getNewImageName();
                    //todo 这里更改了图片目录 1/2
//                    replaceChars = StringUtils.join("![", newImageName, "](images/", newImageName, ")");
                    replaceChars = StringUtils.join("![", newImageName, "](", newImageName, ")");
                    //得到要写入的文件夹路径
                    FileUtils.copyFile(imageFile.getOldImage(), imageFile.getNewImage());
                }
                newStringList.add(replaceChars);
                count++;
            }
            FileUtils.writeLines(markdownFile.getNewMarkdown(), newStringList, false);
        } catch (IOException e) {
            log.error(file.getName());
            log.error("读取文件异常 ===> count=" + count, e);
        }
    }


    private static ImageFile getImageFile(String replaceChars, MarkdownFile markdownFile) {
        //![1591322466820](assets\1591322466820.png)
        //"C:\\Users\\Administrator\\Desktop\\test\\spring-day04.md"

        //该行是md文档的图片链接，得到图片的相对路径
        //assets\1591322466820.png
        String imageName = StringUtils.chop(StringUtils.substringAfterLast(replaceChars, "/"));

        //图片名包含中文，得到图片的后缀名
        String fileSuffix = StringUtils.chop("." + StringUtils.substringAfterLast(replaceChars, "."));

        String relativeImagePath = StringUtils.substringBetween(replaceChars, "(", ")");
        //得到父文件夹地址
        String parentDirectoryPath = markdownFile.getMarkdownParentDirectoryPath();
        //得到图片的绝对路径
        String absoluteImagePath = StringUtils.join(parentDirectoryPath, "\\", relativeImagePath);
        //得到新图片的父路径
        //todo 这里更改了图片目录 2/2
//        String newParentDirectory = markdownFile.getNewParentDirectory() + "\\images";
        String newParentDirectory = markdownFile.getNewParentDirectory();
        //得到新图片地址
        String newImagePath = newParentDirectory + "/" + imageName;
        ImageFile imageFile = ImageFile.builder()
                .oldImageName(imageName)
                .newImageName(imageName)
                .fileSuffix(fileSuffix)
                .oldImage(new File(absoluteImagePath))
                .newParentDirectory(newParentDirectory)
                .newImage(new File(newImagePath))
                .build();

        return imageFile;
    }

    private static MarkdownFile getMarkdownFile(File file) {
        //![1591322466820](assets\1591322466820.png)
        //"C:\\Users\\Administrator\\Desktop\\test\\spring-day04.md"

        //得到md文件名
        String markdownName = file.getName();
        String absolutePath = file.getAbsolutePath();
        String parentDirectoryPath = file.getParent();
        String newMarkdownPath = StringUtils.replace(absolutePath, sourceDirectory, temp);
        String newParentDirectory = StringUtils.substringBeforeLast(newMarkdownPath, "\\" + markdownName);
        MarkdownFile markdownFile = MarkdownFile.builder()
                .markdownName(markdownName)
                .markdownAbsolutPath(absolutePath)
                .markdownParentDirectoryPath(parentDirectoryPath)
                .newParentDirectory(newParentDirectory)
                .newMarkdown(new File(newMarkdownPath))
                .build();

        return markdownFile;
    }

    public static boolean isAlphanumeric(String imageName) {
        String regex = "^[A-Za-z0-9]+$";
        return imageName.matches(regex);
    }

    private static void toZip(File file) {
        //得到md文件的文件名
        String fileName = file.getName();
        //得到父文件夹
        File parentFile = file.getParentFile();

        //标准格式代码
        Project proj = new Project();
        FileSet fileSet = new FileSet();
        fileSet.setProject(proj);
        //设置父文件夹为压缩根目录
        fileSet.setDir(parentFile);
        //将根目录中的图片文件夹添加到压缩FileSet
        String[] include = {"**"};
        fileSet.appendIncludes(include);
        /*//将MD文件添加到压缩FileSet
        fileSet.setFile(file);*/
        Zip zip = new Zip();
        zip.setProject(proj);
        //获得压缩包的名字
        String zipName = file.getName().replace(".md", "");
        //设置压缩文件输出
        zip.setDestFile(new File(targetDirectory + "\\" + zipName + ".zip"));
        zip.addFileset(fileSet);
        zip.setEncoding(encoding);
        zip.execute();
        if (checkZip) {
            //开启创建成功标记
            File successFlag = new File(parentFile.getAbsolutePath() + "\\1_success.status");
            try {
                successFlag.createNewFile();
            } catch (IOException e) {
                log.error(fileName);
                log.error("创建成功标记文件时异常！",e);
            }
        }
    }

    private static boolean checkIsExistZip(File file) {
        //得到md文件的父文件夹
        File parentFile = file.getParentFile();
        File[] files = parentFile.listFiles();
        for (File listFile : files) {
            //如果父文件夹中含有这个文件，则代表已经压缩过了
            if ("1_success.status".equals(listFile.getName())) {
                return true;
            }
        }
        return false;
    }
}